use std::time::Duration;
use std::{fs, path::Path};

use std::sync::Arc;

use crate::m3u8_key::{Key, KeyType};

/// 下载TS 文件
pub async fn download_ts(
    ts_dir: &Path,
    ts_url: &str,
    i: usize,
    key: Arc<Key>,
) -> Result<usize, String> {
    let ts_name = format!("{i}.ts");

    let Ok(ts_resp) = reqwest::get(ts_url).await else { return Err( format!("{ts_url}访问失败") ) } ;

    let Ok(mut bytes) = ts_resp.bytes().await else { return Err(format!("{ts_name} 数据读取失败"))} ;

    // 判断数据是否是TS文件
    if !verify_ts_head(&bytes[0..128]) {
        // println!("数据：{:?}",String::from_utf8_lossy(&bytes));
        // return Err(format!("{ts_name} 非ts数据"));
        let mut retry_times = 0u8;
        loop {
            if retry_times >= 3 {
                break;
            }
            tokio::time::sleep(Duration::from_millis(200)).await;
            let Ok(ts_resp) = reqwest::get(ts_url).await else {
                continue;
             } ;

            let Ok(_bytes) = ts_resp.bytes().await else { 
                continue;
            } ;

            if verify_ts_head(&_bytes[0..128]) {
                bytes = _bytes;
            }

            retry_times += 1;
        }
    }

    let ts_path = ts_dir.join(ts_name);

    if key.ty == KeyType::None {
        fs::write(ts_path.as_path(), bytes).unwrap();
        return Ok(i);
    }

    let ts_data = key.decode(&bytes);

    fs::write(ts_path.as_path(), ts_data).unwrap();

    Ok(i)
}

/// TS 文件的标识数据
const TS_TAG: [u8; 25] = [
    0, 1, 252, 128, 20, 72, 18, 1, 6, 70, 70, 109, 112, 101, 103, 9, 83, 101, 114, 118, 105, 99,
    101, 48, 49,
];

/**
 * 判断数据是否是ts数据
 */
fn verify_ts_head(data: &[u8]) -> bool {
    if data.len() <= TS_TAG.len() {
        return false;
    }

    let mut s_index = 0;
    for (i, c) in data.iter().enumerate() {
        // 首字母匹配
        if &TS_TAG[s_index] == c {
            s_index += 1;
            if s_index == TS_TAG.len() {
                return true;
            }
        } else {
            s_index = 0;
        }
    }
    return false;
}
